using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using Comteck.Dto.Orders;
using Comteck.Dto.Sys;
using Comteck.Ktt.Services.Orders;
using Comteck.Ktt.Services.Sys;
using Comteck.Linq;
using Comteck.Localization;
using Comteck.Winforms;
using Comteck.Winforms.Controls;
using Comteck.Winforms.Data;
using Comteck.Winforms.Infrastructure;
using DevExpress.Utils.Menu;
using DevExpress.Utils.Serializing;
using DevExpress.XtraBars.Navigation;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using ExpressMapper;
using ExpressMapper.Extensions;
using Microsoft.Extensions.DependencyInjection;

namespace Comteck.Ktt.WinUI.Orders {
  /// <summary>
  /// 订单管理
  /// </summary>
  public partial class UcSaleOrder : UcBase {

    #region fields

    private ISaleOrderService saleOrderService;
    private IParameterService parameterService;
    private decimal order_weight = decimal.Zero;
    private CKObservableCollection<SaleOrderDto> mainDataList;


    /// <summary>
    /// 订单商品是否支持拆分操作
    /// </summary>
    [DefaultValue(false)]
    [DXCategory("自定义属性")]
    [Description("是否启用基类鼠标右键 PopupMenuShowing 事件")]
    [XtraSerializableProperty]
    public virtual bool EnableGoodsSplitMenu { get; set; } = false;

    #endregion

    #region ctor

    /// <summary>
    /// 
    /// </summary>
    public UcSaleOrder() {
      InitializeComponent();
    }

    #endregion

    #region form load

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private async void UcSaleOrder_Load(object sender, EventArgs e) {
      if (this.DesignMode) {
        return;
      }

      // service
      saleOrderService = SysGlobal.ServiceProvider.GetRequiredService<ISaleOrderService>();
      parameterService = SysGlobal.ServiceProvider.GetRequiredService<IParameterService>();

      // page
      ucDataNavigator1.barPageSize.EditValue = 1000;
      // 放到调用方去使用
      //ucDataNavigator1.UcDataNavigatorPaged += () => {
      //  btnSearch.PerformClick();
      //};

      gcMain.DataSource = mainDataList = new CKObservableCollection<SaleOrderDto>(this);
      colImportTime.FormatDate();
      colPayDate.FormatDate();

      BindHelper.Bind<EnumMainOrderFlag>(rilpMainOrderFlag);
      BindHelper.Bind<EnumSaleOrderStatus>(rilpStatus);
      BindHelper.Bind<EnumDeliveryStatus>(rilpDeliveryStatus);

      // 限重
      order_weight = (await parameterService.GetValueAsync(EnumParameter.order_weight)).To(10m);

      // 明细添加鼠标右键
      if (gvDetail.EnablePopupMenuShowing && this.EnableGoodsSplitMenu) {
        gvDetail.PopupMenuShowing += this.GvDetail_PopupMenuShowing;
      }
    }

    #endregion

    #region grid

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void gvMain_RowCellStyle(object sender, RowCellStyleEventArgs e) {
      if (!(gvMain.GetRow(e.RowHandle) is SaleOrderDto model)) {
        return;
      }

      // 检查收货地址中是否包含自提点信息，如果未包含则标记为红色
      bool hasAddressError = false;
      if (model.RecipientAddress.IsNotNullOrEmpty() && model.SelfOrgName.IsNotNullOrEmpty()) {
        if (!model.RecipientAddress.Contains(model.SelfOrgName)) {
          hasAddressError = true;
          e.Appearance.ForeColor = Color.Red;
        }
      }

      // 如果已经标记为地址异常，其他颜色不再覆盖
      if (hasAddressError) {
        return;
      }

      switch (e.Column.Name) {
        case nameof(colStatus):
          switch (model.Status) {
            case (int) EnumSaleOrderStatus.未审核:
              e.Appearance.ForeColor = Color.FromArgb((int) EnumGridStatusForeColor.Input);
              break;
            case (int) EnumSaleOrderStatus.已审核:
              e.Appearance.ForeColor = Color.FromArgb((int) EnumGridStatusForeColor.Audit);
              break;
            case (int) EnumSaleOrderStatus.已打印:
              e.Appearance.ForeColor = Color.FromArgb((int) EnumGridStatusForeColor.HasOrder);
              break;
            case (int) EnumSaleOrderStatus.已删除:
              e.Appearance.ForeColor = Color.FromArgb((int) EnumGridStatusForeColor.Cancel);
              break;
            default:
              break;
          }
          break;
        case nameof(colCode):
        case nameof(colGoodsWeight):
          // 超重
          if (model.GoodsWeight > order_weight) {
            e.Appearance.ForeColor = Color.FromArgb((int) EnumGridStatusForeColor.Cancel);
          }
          break;
        case nameof(colMainOrderFlag):
          // 超重
          switch (model.MainOrderFlag) {
            case (int) EnumMainOrderFlag.正常:
              break;
            case (int) EnumMainOrderFlag.已拆单:
              e.Appearance.ForeColor = Color.FromArgb((int) EnumGridStatusForeColor.Input);
              break;
            case (int) EnumMainOrderFlag.子单:
              e.Appearance.ForeColor = Color.FromArgb((int) EnumGridStatusForeColor.Upload);
              break;
            default:
              break;
          }
          break;
        default:
          break;
      }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public async void gvMain_FocusedRowObjectChanged(object sender, FocusedRowObjectChangedEventArgs e) {
      if (!(gvMain.GetFocusedRow() is SaleOrderDto model)) {
        gcDetail.DataSource = null;
        gcPath.DataSource = null;
        return;
      }

      ajaxLoad.Show();
      try {
        var goodsResult = await saleOrderService.GetDetailListByOrderIdAsync(model.Id);
        var pathResult = await saleOrderService.GetPathListByOrderIdAsync(model.Id);
        gcDetail.DataSource = goodsResult;
        gvPath.BeginUpdate();
        gcPath.DataSource = pathResult;
        gvPath.BestFitColumns();
        gvPath.EndUpdate();
      } catch (Exception ex) {
        gcDetail.DataSource = null;
        gcPath.DataSource = null;
        this.ShowMsg($"查询明细失败，{ex.Message}");
      }
      ajaxLoad.Hide();
    }

    #endregion

    #region search

    /// <summary>
    /// 
    /// </summary>
    /// <param name="searchModel"></param>
    /// <returns></returns>
    public async Task SearchDataAsync(SaleOrderQuery searchModel) {
      // 分页
      if (ucDataNavigator1.GetPageData(searchModel) == false) {
        return;
      }

      // search
      ajaxLoad.Show();
      var result = await saleOrderService.GetPageListAsync(searchModel);
      ajaxLoad.Hide();

      // search result
      if (result.Code == 1) {
        gvMain.BeginUpdate();
        result.Data.MapTo(mainDataList, x => x.Id, x => x.Id);
        gvMain.BestFitColumns();
        gvMain.EndUpdate();
        ucDataNavigator1.InitPageData(result);
      } else {
        mainDataList.Clear();
        this.ShowMsg(BaseResources.Search_Failed_Reason, result.Message);
      }
    }

    #endregion

    #region 放入回收站

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public async Task RecycleDataAsync() {
      var rows = gvMain.GetSelectedRowsList<SaleOrderDto>();
      if (rows.IsNullOrEmpty()) {
        return;
      }

      var dialog = this.ShowMsg("您确定要将选中的记录放入回收站吗", "提示", MessageBoxButtons.YesNo,
        MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
      if (dialog == DialogResult.No) {
        return;
      }

      try {
        ajaxLoad.Show();
        await saleOrderService.RecycleBatchAsync(rows.Select(x => x.Id).ToList());
        ajaxLoad.Hide();
        mainDataList.RemoveAll(x => rows.Any(y => y.Id == x.Id));
        this.ShowMsg(BaseResources.Execute_Success);
      } catch (Exception ex) {
        this.ShowMsg(BaseResources.Execute_Faild, ex.Message);
      } finally {
        ajaxLoad.Hide();
      }
    }

    #endregion

    #region 移出回收站

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public async Task UnRecycleDataAsync() {
      var rows = gvMain.GetSelectedRowsList<SaleOrderDto>();
      if (rows.IsNullOrEmpty()) {
        return;
      }

      var dialog = this.ShowMsg("您确定要将选中的订单还原到正常订单吗", "提示", MessageBoxButtons.YesNo,
        MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
      if (dialog == DialogResult.No) {
        return;
      }

      try {
        ajaxLoad.Show();
        await saleOrderService.UnRecycleBatchAsync(rows.Select(x => x.Id).ToList());
        ajaxLoad.Hide();
        mainDataList.RemoveAll(x => rows.Any(y => y.Id == x.Id));
        this.ShowMsg(BaseResources.Execute_Success);
      } catch (Exception ex) {
        this.ShowMsg(BaseResources.Execute_Faild, ex.Message);
      } finally {
        ajaxLoad.Hide();
      }
    }

    #endregion

    #region delete

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public async Task DeleteDataAsync() {
      var rows = gvMain.GetSelectedRowsList<SaleOrderDto>();
      if (rows.IsNullOrEmpty()) {
        return;
      }

      var dialog = this.ShowMsg(BaseResources.Delete_Selected_Confirm, "提示", MessageBoxButtons.YesNo,
        MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
      if (dialog == DialogResult.No) {
        return;
      }

      try {
        ajaxLoad.Show();
        await saleOrderService.DeleteBatchAsync(rows.Select(x => x.Id).ToList());
        ajaxLoad.Hide();
        mainDataList.RemoveAll(x => rows.Any(y => y.Id == x.Id));
        this.ShowMsg(BaseResources.Delete_Success);
      } catch (Exception ex) {
        this.ShowMsg(BaseResources.Delete_Failed_Reason, ex.Message);
      } finally {
        ajaxLoad.Hide();
      }
    }

    #endregion

    #region 添加鼠标右键

    /// <summary>
    /// 鼠标右键
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void GvDetail_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e) {
      // 对象
      if (!(sender is GridView gridView)) {
        return;
      }

      // 非自定义列
      if (e.HitInfo.InGroupPanel || e.HitInfo.InFilterPanel || e.MenuType == GridMenuType.Column) {
        return;
      }

      if (e.MenuType == GridMenuType.Row) {
        // 复制
        var menu_copy = new DXSubMenuItem("订单操作") {
          BeginGroup = true
        };
        menu_copy.ImageOptions.ImageUri = DevExpress.Images.DXImages.SplitAppointment;

        // 拆分
        var menu_copy_cell = new DXMenuItem("将多个商品拆分到新订单上");
        menu_copy_cell.ImageOptions.ImageUri = DevExpress.Images.DXImages.SplitAppointment;
        menu_copy_cell.Click += async (x, y) => {
          await this.SplitGoods2NewOrderAsync();
        };

        // 分解商品
        var menu_copy_select = new DXMenuItem("将一个商品分解成多个订单");
        menu_copy_select.ImageOptions.ImageUri = DevExpress.Images.DXImages.SplitAppointment;
        menu_copy_select.Click += (x, y) => {
          this.SplitOrder(this.ParentForm);
        };

        menu_copy.Items.Add(menu_copy_cell);
        menu_copy.Items.Add(menu_copy_select);

        e.Menu.Items.Add(menu_copy);
      }
    }

    #endregion

    #region 将多个商品拆分到新订单上

    /// <summary>
    /// 将多个商品拆分到新订单上
    /// </summary>
    /// <returns></returns>
    public async Task SplitGoods2NewOrderAsync() {
      if (!(gvMain.GetFocusedRow() is SaleOrderDto orderDto)) {
        return;
      }

      if (orderDto.MainOrderFlag == (int) EnumMainOrderFlag.子单) {
        this.ShowMsg($"{EnumMainOrderFlag.子单}不允许拆单");
        return;
      }

      var detailList = gvDetail.GetSelectedRowsList<SaleOrderDetailDto>();
      if (detailList.IsNullOrEmpty()) {
        return;
      }

      var newTotalWeight = detailList.Sum(x => x.TotalWeight);
      var msg = newTotalWeight <= order_weight ? BaseResources.Execute_Confirm : $"新订单的总重量 {newTotalWeight} 超过限重 {order_weight}，您确定还要拆分吗？";

      var dialog = this.ShowMsg(msg, "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
      if (dialog == DialogResult.No) {
        return;
      }

      try {
        ajaxLoad.Show();
        var result = await saleOrderService.SplitGoods2NewOrderAsync(orderDto.Id, detailList.Select(x => x.Id).ToList());
        ajaxLoad.Hide();

        if (result.Code == 1) {
          result.Data.MainOrder.MapTo(orderDto);
          mainDataList.Insert(gvMain.FocusedRowHandle + 1, result.Data.NewOrder);
          //mainDataList.Add(result.Data.NewOrder);
          this.gvMain_FocusedRowObjectChanged(gvMain, null);
          this.ShowMsg($"新订单创建成功，订单号为 {result.Data.NewOrder.Code}");
        } else {
          this.ShowMsg($"拆单失败，{result.Message}");
        }
      } catch (Exception ex) {
        ajaxLoad.Hide();
        this.ShowMsg($"拆单失败，{ex.Message}");
      }

    }

    #endregion

    #region 拆单

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public void SplitOrder(Form owner) {
      if (!(gvMain.GetFocusedRow() is SaleOrderDto orderDto)) {
        return;
      }

      if (!(gvDetail.GetFocusedRow() is SaleOrderDetailDto orderDetailDto)) {
        return;
      }

      if (orderDto.MainOrderFlag == (int) EnumMainOrderFlag.子单) {
        this.ShowMsg($"{EnumMainOrderFlag.子单}不允许拆单");
        return;
      }

      var form = SysGlobal.ServiceProvider.GetRequiredService<FrmSaleOrderDetailSplitAction>();
      form.OrderDto = orderDto;
      form.OrderDetailDto = orderDetailDto;
      form.ImportAction = (list) => {
        if (list.IsNullOrEmpty()) {
          return false;
        }

        list.MapTo(mainDataList, x => x.Id, x => x.Id, EnumMapperType.AddOrUpdate);
        this.gvMain_FocusedRowObjectChanged(gvMain, null);
        return true;
      };
      form.Owner = owner;
      form.ShowDialog();
    }

    #endregion

    #region 取消拆单

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public async Task CombineOrderAsync() {
      if (!(gvMain.GetFocusedRow() is SaleOrderDto orderDto)) {
        return;
      }

      if (orderDto.MainOrderFlag != (int) EnumMainOrderFlag.已拆单) {
        this.ShowMsg($"请选择 {EnumMainOrderFlag.已拆单} 的订单");
        return;
      }

      var dialog = this.ShowMsg($"您确定要将订单号为 {orderDto.MainCode}，跟团号为 {orderDto.MainGroupNumber} 的订单合并回来吗？", "提示", MessageBoxButtons.YesNo,
        MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
      if (dialog == DialogResult.No) {
        return;
      }

      ajaxLoad.Show();
      var result = await saleOrderService.CombineOrderAsync(orderDto.Id);
      ajaxLoad.Hide();

      if (result.Code == 1) {
        result.Data.MainOrder.MapTo(orderDto);
        mainDataList.RemoveAll(x => result.Data.SubOrderList.Any(y => y.Id == x.Id));
        gvMain_FocusedRowObjectChanged(gvMain, null);
        this.ShowMsg("取消拆单成功");
      } else {
        this.ShowMsg($"取消拆单失败，{result.Message}");
      }
    }

    #endregion

    #region 审核/反审核

    public async Task AuditAsync() {
      var rows = gvMain.GetSelectedRowsList<SaleOrderDto>().Where(x => x.Status == (int) EnumSaleOrderStatus.未审核);
      if (rows.IsNullOrEmpty()) {
        return;
      }

      var dialog = this.ShowMsg(BaseResources.Execute_Confirm, "提示", MessageBoxButtons.YesNo,
        MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
      if (dialog == DialogResult.No) {
        return;
      }

      ajaxLoad.Show();
      var result = await saleOrderService.AuditBatchAsync(rows.Select(x => x.Id).ToList());
      ajaxLoad.Hide();

      if (result.Code == 1) {
        result.Data.MapTo(mainDataList, x => x.Id, x => x.Id, EnumMapperType.AddOrUpdate);
        this.ShowMsg(BaseResources.Audit_Success);
      } else {
        this.ShowMsg(BaseResources.Audit_Failed_Reason, result.Message);
      }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public async Task AuditForceAsync() {
      var rows = gvMain.GetSelectedRowsList<SaleOrderDto>().Where(x => x.Status == (int) EnumSaleOrderStatus.未审核);
      if (rows.IsNullOrEmpty()) {
        return;
      }

      var dialog = this.ShowMsg(BaseResources.Execute_Confirm, "提示", MessageBoxButtons.YesNo,
        MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
      if (dialog == DialogResult.No) {
        return;
      }

      ajaxLoad.Show();
      var result = await saleOrderService.ForceAuditBatchAsync(rows.Select(x => x.Id).ToList());
      ajaxLoad.Hide();

      if (result.Code == 1) {
        result.Data.MapTo(mainDataList, x => x.Id, x => x.Id, EnumMapperType.AddOrUpdate);
        this.ShowMsg(BaseResources.Audit_Success);
      } else {
        this.ShowMsg(BaseResources.Audit_Failed_Reason, result.Message);
      }
    }

    #endregion

    #region 打印

    /// <summary>
    /// print
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public async Task PrintAsync(string menuId) {
      var list = gvMain.GetSelectedRowsList<SaleOrderDto>();
      if (list?.Count <= 0) {
        this.ShowMsg("请选择需要打印的记录");
        return;
      }

      if (list.Any(x => !EnumSaleOrderStatusList.能打印.Contains(x.Status))) {
        this.ShowMsg("请选择已审核的记录");
        return;
      }

      // 查询运单号没的记录
      var noDeliveryOrderCount = list.Count(x => x.DeliveryCode.IsNullOrEmpty());
      if (noDeliveryOrderCount > 0) {
        var dialog = this.ShowMsg($"您选择的共有 {noDeliveryOrderCount} 个订单无运单号，是否继续打印？", "提示", MessageBoxButtons.YesNo,
          MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
        if (dialog == DialogResult.No) {
          return;
        }
      }

      // print
      var printList = new List<dynamic>();
      printList.AddRange(list.Select(x => x.Id).ToList());
      ajaxLoad.Show();
      var sucess = await LocalDbDataHelper.OpenPrintDialog(menuId, printList, false);
      ajaxLoad.Hide();

      // 打印成功，则更新状态和数量
      if (sucess) {
        var result = await saleOrderService.UpdateStatusAfterPrintAsync(list.Select(x => x.Id).ToList());
        result.MapTo(mainDataList, x => x.Id, x => x.Id, EnumMapperType.AddOrUpdate);
      }
    }

    #endregion

    #region 反打印

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public async Task UnPrintAsync() {
      var rows = gvMain.GetSelectedRowsList<SaleOrderDto>();
      if (rows.IsNullOrEmpty()) {
        return;
      }

      var dialog = this.ShowMsg(BaseResources.Execute_Confirm, "提示", MessageBoxButtons.YesNo,
        MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
      if (dialog == DialogResult.No) {
        return;
      }

      ajaxLoad.Show();
      var result = await saleOrderService.UnPrintBatchAsync(rows.Select(x => x.Id).ToList());
      ajaxLoad.Hide();

      if (result.Code == 1) {
        result.Data.MapTo(mainDataList, x => x.Id, x => x.Id, EnumMapperType.AddOrUpdate);
        this.ShowMsg(BaseResources.Execute_Success);
      } else {
        this.ShowMsg(BaseResources.Execute_Faild, result.Message);
      }
    }

    #endregion

    #region 反审核

    public async Task UnAuditAsync() {
      var rows = gvMain.GetSelectedRowsList<SaleOrderDto>();
      if (rows.IsNullOrEmpty()) {
        return;
      }

      var dialog = this.ShowMsg(BaseResources.Execute_Confirm, "提示", MessageBoxButtons.YesNo,
        MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
      if (dialog == DialogResult.No) {
        return;
      }

      ajaxLoad.Show();
      var result = await saleOrderService.UnAuditBatchAsync(rows.Select(x => x.Id).ToList());
      ajaxLoad.Hide();

      if (result.Code == 1) {
        result.Data.MapTo(mainDataList, x => x.Id, x => x.Id, EnumMapperType.AddOrUpdate);
        this.ShowMsg(BaseResources.Execute_Success);
      } else {
        this.ShowMsg(BaseResources.Execute_Faild, result.Message);
      }
    }

    #endregion

    #region 重刷商品重量

    /// <summary>
    /// 重刷商品重量
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public async Task RefreshWeightAsync() {
      var rows = gvMain.GetSelectedRowsList<SaleOrderDto>();
      if (rows.IsNullOrEmpty()) {
        return;
      }

      var dialog = this.ShowMsg(BaseResources.Execute_Confirm, "提示", MessageBoxButtons.YesNo,
        MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
      if (dialog == DialogResult.No) {
        return;
      }

      ajaxLoad.Show();
      try {
        var result = await saleOrderService.RefreshWeightAsync(rows.Select(x => x.Id).ToList());
        result.MapTo(mainDataList, x => x.Id, x => x.Id, EnumMapperType.AddOrUpdate);
        this.ShowMsg(BaseResources.Execute_Success);
      } catch (Exception ex) {
        this.ShowMsg(BaseResources.Execute_Faild, ex.Message);
      }
      ajaxLoad.Hide();
      this.gvMain_FocusedRowObjectChanged(gvMain, null);
    }

    #endregion

    #region 双击启用编辑

    /// <summary>
    /// 双击行时启用编辑
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void gvMain_DoubleClick(object sender, EventArgs e) {
      if (!(gvMain.GetFocusedRow() is SaleOrderDto orderDto)) {
        return;
      }

      // 只允许编辑未删除的订单
      if (orderDto.Status == (int)EnumSaleOrderStatus.已删除) {
        return;
      }

      var hitInfo = gvMain.CalcHitInfo(gcMain.PointToClient(Control.MousePosition));
      if (hitInfo.InRowCell) {
        var column = hitInfo.Column;
        if (column != null) {
          // 检查是否为可编辑列
          if (column.FieldName == "Recipient" || 
              column.FieldName == "RecipientPhone" || 
              column.FieldName == "RecipientAddress" || 
              column.FieldName == "GroupDesc" || 
              column.FieldName == "BuyUserDesc") {
            // 临时启用编辑模式
            gvMain.OptionsBehavior.Editable = true;
            gvMain.FocusedColumn = column;
            gvMain.ShowEditor();
          }
        }
      }
    }

    #endregion

    #region 编辑器关闭事件

    /// <summary>
    /// 编辑器关闭后恢复不可编辑状态
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void gvMain_HiddenEditor(object sender, EventArgs e) {
      // 编辑器关闭后，恢复为不可编辑状态
      gvMain.OptionsBehavior.Editable = false;
    }

    #endregion

    #region 单元格编辑控制

    /// <summary>
    /// 显示编辑器时控制是否允许编辑
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void gvMain_ShowingEditor(object sender, System.ComponentModel.CancelEventArgs e) {
      if (!(gvMain.GetFocusedRow() is SaleOrderDto orderDto)) {
        e.Cancel = true;
        return;
      }

      // 只允许编辑未删除的订单
      if (orderDto.Status == (int)EnumSaleOrderStatus.已删除) {
        e.Cancel = true;
        return;
      }

      // 获取当前编辑的列
      var column = gvMain.FocusedColumn;
      if (column == null) {
        e.Cancel = true;
        return;
      }

      // 只允许编辑特定字段
      if (column.FieldName != "Recipient" && 
          column.FieldName != "RecipientPhone" && 
          column.FieldName != "RecipientAddress" && 
          column.FieldName != "GroupDesc" && 
          column.FieldName != "BuyUserDesc") {
        e.Cancel = true;
      }
    }

    #endregion

    #region 单元格编辑保存

    /// <summary>
    /// 单元格值改变后保存
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private async void gvMain_CellValueChanged(object sender, CellValueChangedEventArgs e) {
      if (!(gvMain.GetRow(e.RowHandle) is SaleOrderDto orderDto)) {
        return;
      }

      // 只允许编辑特定字段
      if (e.Column.FieldName != "Recipient" && 
          e.Column.FieldName != "RecipientPhone" && 
          e.Column.FieldName != "RecipientAddress" && 
          e.Column.FieldName != "GroupDesc" && 
          e.Column.FieldName != "BuyUserDesc") {
        return;
      }

      try {
        ajaxLoad.Show();
        var result = await saleOrderService.UpdateAsync(orderDto);
        ajaxLoad.Hide();

        if (result.Code == 1) {
          result.Data.MapTo(orderDto);
          this.ShowMsg(BaseResources.Save_Success);
        } else {
          this.ShowMsg(BaseResources.Save_Failed_Reason, result.Message);
          // 保存失败，恢复原值
          gvMain.RefreshRow(e.RowHandle);
        }
      } catch (Exception ex) {
        ajaxLoad.Hide();
        this.ShowMsg(BaseResources.Save_Failed_Reason, ex.Message);
        // 保存失败，恢复原值
        gvMain.RefreshRow(e.RowHandle);
      }
    }

    #endregion

    #region 导出

    /// <summary>
    /// export
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public void ExportDialog() {
      gvMain.ExportDialog();
    }

    #endregion
  }
}
